/*
 * Remmina - The GTK+ Remote Desktop Client
 * Copyright (C) 2009 - Vic Lee 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA.
 */
 
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include "remminachatwindow.h"

G_DEFINE_TYPE (RemminaChatWindow, remmina_chat_window, GTK_TYPE_WINDOW)

enum {
    SEND_SIGNAL,
    LAST_SIGNAL
};

static guint remmina_chat_window_signals[LAST_SIGNAL] = { 0 };

static void
remmina_chat_window_class_init (RemminaChatWindowClass *klass)
{
    remmina_chat_window_signals[SEND_SIGNAL] =
        g_signal_new ("send",
            G_TYPE_FROM_CLASS (klass),
            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
            G_STRUCT_OFFSET (RemminaChatWindowClass, send),
            NULL, NULL,
            g_cclosure_marshal_VOID__STRING,
            G_TYPE_NONE, 1,
            G_TYPE_STRING);
}

static void
remmina_chat_window_init (RemminaChatWindow *window)
{
    window->history_text = NULL;
    window->send_text = NULL;
}

static void
remmina_chat_window_clear_send_text (GtkWidget *widget, RemminaChatWindow *window)
{
    GtkTextBuffer *buffer;
    
    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->send_text));
    gtk_text_buffer_set_text (buffer, "", -1);
    gtk_widget_grab_focus (window->send_text);
}

static gboolean
remmina_chat_window_scroll_proc (RemminaChatWindow *window)
{
    GtkTextBuffer *buffer;
    GtkTextIter iter;

    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->history_text));
    gtk_text_buffer_get_end_iter (buffer, &iter);
    gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (window->history_text), &iter, 0.0, FALSE, 0.0, 0.0);

    return FALSE;
}

static void
remmina_chat_window_append_text (RemminaChatWindow *window, const gchar *name, const gchar *tagname, const gchar *text)
{
    GtkTextBuffer *buffer;
    GtkTextIter iter;
    gchar *ptr;

    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->history_text));

    if (name)
    {
        ptr = g_strdup_printf ("(%s) ", name);
        gtk_text_buffer_get_end_iter (buffer, &iter);
        if (tagname)
        {
            gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, ptr, -1, tagname, NULL);
        }
        else
        {
            gtk_text_buffer_insert (buffer, &iter, ptr, -1);
        }
        g_free (ptr);
    }

    if (text && text[0] != 0)
    {
        gtk_text_buffer_get_end_iter (buffer, &iter);
        if (text[strlen(text) - 1] == '\n')
        {
            gtk_text_buffer_insert (buffer, &iter, text, -1);
        }
        else
        {
            ptr = g_strdup_printf ("%s\n", text);
            gtk_text_buffer_insert (buffer, &iter, ptr, -1);
            g_free (ptr);
        }
    }

    /* Use g_idle_add to make the scroll happen after the text has been actually updated */
    g_idle_add ((GSourceFunc) remmina_chat_window_scroll_proc, window);
}

static void
remmina_chat_window_send (GtkWidget *widget, RemminaChatWindow *window)
{
    GtkTextBuffer *buffer;
    GtkTextIter start, end;
    gchar *text;

    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->send_text));
    gtk_text_buffer_get_bounds (buffer, &start, &end);
    text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);

    if (!text || text[0] == '\0') return;

    g_signal_emit_by_name (G_OBJECT (window), "send", text);

    remmina_chat_window_append_text (window, g_get_user_name (), "sender-foreground", text);

    g_free (text);

    remmina_chat_window_clear_send_text (widget, window);
}

static gboolean
remmina_chat_window_send_text_on_key (GtkWidget *widget, GdkEventKey *event, RemminaChatWindow *window)
{
    if (event->keyval == GDK_KEY_Return)
    {
        remmina_chat_window_send (widget, window);
        return TRUE;
    }
    return FALSE;
}

GtkWidget*
remmina_chat_window_new (GtkWindow *parent, const gchar *chat_with)
{
    RemminaChatWindow *window;
    gchar buf[100];
    GtkWidget *table;
    GtkWidget *scrolledwindow;
    GtkWidget *widget;
    GtkWidget *image;
    GtkTextBuffer *buffer;

    window = REMMINA_CHAT_WINDOW (g_object_new (REMMINA_TYPE_CHAT_WINDOW, NULL));

    if (parent)
    {
        gtk_window_set_transient_for (GTK_WINDOW (window), parent);
    }

    /* Title */
    g_snprintf (buf, sizeof (buf), _("Chat with %s"), chat_with);
    gtk_window_set_title (GTK_WINDOW (window), buf);
    gtk_window_set_default_size (GTK_WINDOW (window), 450, 300);

    /* Main container */
    table = gtk_table_new (3, 2, FALSE);
    gtk_widget_show (table);
    gtk_table_set_row_spacings (GTK_TABLE (table), 4);
    gtk_table_set_col_spacings (GTK_TABLE (table), 4);
    gtk_container_set_border_width (GTK_CONTAINER (table), 8);
    gtk_container_add (GTK_CONTAINER (window), table);

    /* Chat history */
    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (scrolledwindow);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
        GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
    gtk_table_attach_defaults (GTK_TABLE (table), scrolledwindow, 0, 2, 0, 1);

    widget = gtk_text_view_new ();
    gtk_widget_show (widget);
    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (widget), GTK_WRAP_WORD_CHAR);
    gtk_text_view_set_editable (GTK_TEXT_VIEW (widget), FALSE);
    gtk_container_add (GTK_CONTAINER (scrolledwindow), widget);

    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
    gtk_text_buffer_create_tag (buffer, "sender-foreground", "foreground", "blue", NULL);
    gtk_text_buffer_create_tag (buffer, "receiver-foreground", "foreground", "red", NULL);

    window->history_text = widget;

    /* Chat message to be sent */
    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (scrolledwindow);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
        GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
    gtk_table_attach (GTK_TABLE (table), scrolledwindow, 0, 1, 1, 3,
        GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);

    widget = gtk_text_view_new ();
    gtk_widget_show (widget);
    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (widget), GTK_WRAP_WORD_CHAR);
    gtk_container_add (GTK_CONTAINER (scrolledwindow), widget);
    g_signal_connect (G_OBJECT (widget), "key-press-event",
        G_CALLBACK (remmina_chat_window_send_text_on_key), window);

    window->send_text = widget;

    /* Send button */
    image = gtk_image_new_from_icon_name ("document-send", GTK_ICON_SIZE_BUTTON);
    gtk_widget_show (image);

    widget = gtk_button_new_with_mnemonic (_("_Send"));
    gtk_widget_show (widget);
    gtk_button_set_image (GTK_BUTTON (widget), image);
    gtk_table_attach (GTK_TABLE (table), widget, 1, 2, 1, 2, 0, 0, 0, 0);
    g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (remmina_chat_window_send), window);

    /* Clear button */
    image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON);
    gtk_widget_show (image);

    widget = gtk_button_new_with_mnemonic (_("_Clear"));
    gtk_widget_show (widget);
    gtk_button_set_image (GTK_BUTTON (widget), image);
    gtk_table_attach (GTK_TABLE (table), widget, 1, 2, 2, 3, 0, 0, 0, 0);
    g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (remmina_chat_window_clear_send_text), window);

    gtk_widget_grab_focus (window->send_text);

    return GTK_WIDGET (window);
}

void
remmina_chat_window_receive (RemminaChatWindow *window, const gchar *name, const gchar *text)
{
    remmina_chat_window_append_text (window, name, "receiver-foreground", text);
}


